package cn.gok.lambda;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.function.*;

//自定义学生类
class Student{
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class 常用函数式接口 {
    public static void main(String[] args) {
        /*
        Runnable接口();
        doRun(()->{
            System.out.println("XXXXXX");
        });  //将lambda表达式作为 函数式接口的实现对象，直接传入。

         */
        //Consumer接口();
       // Supplier接口();
       // Function接口();
        Predicate接口();
        //简化lambda();
    }

    private static void Predicate接口() {
        //有1个入参，有一个boolean返回值。看成是Function的特例。
        //判断1个数，是不是3位数
        //Predicate<Integer> precicate = i->{return i>=100;};
        Predicate<Integer> precicate = i->i>=100;
        System.out.println(precicate.test(99));
        System.out.println(precicate.test(101));
        Predicate<Integer> precicate2 = i->i%2==0; //判断是否是偶数
        System.out.println(precicate.and(precicate2).test(102)); //&&
        System.out.println(precicate.or(precicate2).test(102));  //||
        //and。or
    }

    private static void 简化lambda() {
        //1 消费者的简化
        //Consumer<String> con = (str)->System.out.println(str);  //如果消费者入参，恰好是唯一代码的入参。
        Consumer<String> con = System.out::println;
        //2 函数的简化.将给定的字符串，转成Integer.静态函数的简化
        //Function<String,Integer> function = (str)->{return Integer.parseInt(str)};
        Function<String,Integer> function = Integer::parseInt;
        //函数的简化2：获得指定字符串的子串.实例方法的简化
        String str = "abcdefg";
        //Function<Integer,String> function2 = (n)->{return str.substring(n)};
        Function<Integer,String> function2 = str::substring;
        System.out.println(function2.apply(2));
        //函数的简化3：获得指定入参的构造函数产生的对象。
        //BiFunciton:2个入参，1个返回值。
        //BiFunction<String,Integer,Student> biFunction = (name,age)->{return new Student(name,age);};
        BiFunction<String,Integer,Student> biFunction = Student::new; //两个入参，恰好是构造函数的入参。 构造函数的简化
        System.out.println(biFunction.apply("老白",28));
    }

    private static void Function接口() {
        //1个入参，有返回。获取字符串长度.
        Function<String,Integer> function1 = str->str.length();   // (str)->{return stu.length();}
        //执行函数
        System.out.println(function1.apply("我是老白"));   //通过apply来执行函数
        //对入参的数+100
        Function<Integer,Integer> function2 = i->i+100;

        //函数的连接调用  compose。function1执行的结果(Integer），作为function2的·入参。
        System.out.println(function2.compose(function1).apply("我是老白"));

        //小练习:function1：获得入参float的平方，
       // function2：获得入参float*100的值.
        // 要求：通过定义两个Function 接口及对应的lambda，计算   (16的平方)*100
        Function<Float,Float> function3 = r->r*r;
        Function<Float,Float> function4 = r->r*100;
        System.out.println(function4.compose(function3).apply(16.0f));
    }

    private static void Supplier接口() {
        //没有入参，有返回值。泛型是返回值类型。
        Supplier<String> sup = ()->new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        System.out.println("执行结果:"+sup.get());
    }

    private static void Consumer接口() {
        //有1个入参，没有返回值
        Consumer<String> con1 = (String str)->{
            str += "!";
            System.out.println(str);
        };
        Consumer<String> con2 = (String str)->{
            str += "*";
            System.out.println(str);
        };
        con1.accept("abc");//用accept执行lambda.
        con1.andThen(con2).accept("abc"); //两次消费
    }

    private static void doRun(Runnable r){
        r.run();
    }
    private static void Runnable接口() {

        /*jdk1.8之前，可以使用匿名内部类实现*/
        int x = 100;
        Runnable r = new Runnable() {
            private int y;
            private void test(){}
            @Override
            public void run() {
                System.out.println("!!!x="+x);
            }
        };
        Runnable r2 = ()->{
            int y = 0;
            System.out.println("!!!x="+x);
        };
        r2.run();//用run执行lambda
    }
}
